/*
* Copyright 2016 Nu-book Inc.
* Copyright 2016 ZXing authors
*/
// SPDX-License-Identifier: Apache-2.0

#include "PDFCodewordDecoder.h"
#include "BitArray.h"
#include "ZXAlgorithms.h"

#include <algorithm>
#include <array>
#include <cstdint>
#include <limits>

namespace ZXing {
namespace Pdf417 {

static constexpr const int SYMBOL_COUNT = 2787;


/**
* The sorted table of all possible symbols. Extracted from the PDF417
* specification. The index of a symbol in this table corresponds to the
* index into the codeword table.
* Note: stored in the table are only the 16 least significant bits (of 17),
* each full symbol is preceded by a 1-bit, see getSymbol();
*/
static constexpr const std::array<uint16_t, 2787> SYMBOL_TABLE = {
	0x025e, 0x027a, 0x029e, 0x02bc, 0x02f2, 0x02f4, 0x032e, 0x034e, 0x035c, 0x0396, 0x03a6, 0x03ac,
	0x0422, 0x0428, 0x0436, 0x0442, 0x0444, 0x0448, 0x0450, 0x045e, 0x0466, 0x046c, 0x047a, 0x0482,
	0x049e, 0x04a0, 0x04bc, 0x04c6, 0x04d8, 0x04ee, 0x04f2, 0x04f4, 0x0504, 0x0508, 0x0510, 0x051e,
	0x0520, 0x053c, 0x0540, 0x0578, 0x0586, 0x058c, 0x0598, 0x05b0, 0x05be, 0x05ce, 0x05dc, 0x05e2,
	0x05e4, 0x05e8, 0x05f6, 0x062e, 0x064e, 0x065c, 0x068e, 0x069c, 0x06b8, 0x06de, 0x06fa, 0x0716,
	0x0726, 0x072c, 0x0746, 0x074c, 0x0758, 0x076e, 0x0792, 0x0794, 0x07a2, 0x07a4, 0x07a8, 0x07b6,
	0x0822, 0x0828, 0x0842, 0x0848, 0x0850, 0x085e, 0x0866, 0x086c, 0x087a, 0x0882, 0x0884, 0x0890,
	0x089e, 0x08a0, 0x08bc, 0x08c6, 0x08cc, 0x08d8, 0x08ee, 0x08f2, 0x08f4, 0x0902, 0x0908, 0x091e,
	0x0920, 0x093c, 0x0940, 0x0978, 0x0986, 0x0998, 0x09b0, 0x09be, 0x09ce, 0x09dc, 0x09e2, 0x09e4,
	0x09e8, 0x09f6, 0x0a08, 0x0a10, 0x0a1e, 0x0a20, 0x0a3c, 0x0a40, 0x0a78, 0x0af0, 0x0b06, 0x0b0c,
	0x0b18, 0x0b30, 0x0b3e, 0x0b60, 0x0b7c, 0x0b8e, 0x0b9c, 0x0bb8, 0x0bc2, 0x0bc4, 0x0bc8, 0x0bd0,
	0x0bde, 0x0be6, 0x0bec, 0x0c2e, 0x0c4e, 0x0c5c, 0x0c62, 0x0c64, 0x0c68, 0x0c76, 0x0c8e, 0x0c9c,
	0x0cb8, 0x0cc2, 0x0cc4, 0x0cc8, 0x0cd0, 0x0cde, 0x0ce6, 0x0cec, 0x0cfa, 0x0d0e, 0x0d1c, 0x0d38,
	0x0d70, 0x0d7e, 0x0d82, 0x0d84, 0x0d88, 0x0d90, 0x0d9e, 0x0da0, 0x0dbc, 0x0dc6, 0x0dcc, 0x0dd8,
	0x0dee, 0x0df2, 0x0df4, 0x0e16, 0x0e26, 0x0e2c, 0x0e46, 0x0e58, 0x0e6e, 0x0e86, 0x0e8c, 0x0e98,
	0x0eb0, 0x0ebe, 0x0ece, 0x0edc, 0x0f0a, 0x0f12, 0x0f14, 0x0f22, 0x0f28, 0x0f36, 0x0f42, 0x0f44,
	0x0f48, 0x0f50, 0x0f5e, 0x0f66, 0x0f6c, 0x0fb2, 0x0fb4, 0x1022, 0x1028, 0x1042, 0x1048, 0x1050,
	0x105e, 0x107a, 0x1082, 0x1084, 0x1090, 0x109e, 0x10a0, 0x10bc, 0x10c6, 0x10cc, 0x10d8, 0x10ee,
	0x10f2, 0x10f4, 0x1102, 0x111e, 0x1120, 0x113c, 0x1140, 0x1178, 0x1186, 0x1198, 0x11b0, 0x11be,
	0x11ce, 0x11dc, 0x11e2, 0x11e4, 0x11e8, 0x11f6, 0x1208, 0x121e, 0x1220, 0x1278, 0x12f0, 0x130c,
	0x1330, 0x133e, 0x1360, 0x137c, 0x138e, 0x139c, 0x13b8, 0x13c2, 0x13c8, 0x13d0, 0x13de, 0x13e6,
	0x13ec, 0x1408, 0x1410, 0x141e, 0x1420, 0x143c, 0x1440, 0x1478, 0x14f0, 0x15e0, 0x160c, 0x1618,
	0x1630, 0x163e, 0x1660, 0x167c, 0x16c0, 0x16f8, 0x171c, 0x1738, 0x1770, 0x177e, 0x1782, 0x1784,
	0x1788, 0x1790, 0x179e, 0x17a0, 0x17bc, 0x17c6, 0x17cc, 0x17d8, 0x17ee, 0x182e, 0x1834, 0x184e,
	0x185c, 0x1862, 0x1864, 0x1868, 0x1876, 0x188e, 0x189c, 0x18b8, 0x18c2, 0x18c8, 0x18d0, 0x18de,
	0x18e6, 0x18ec, 0x18fa, 0x190e, 0x191c, 0x1938, 0x1970, 0x197e, 0x1982, 0x1984, 0x1990, 0x199e,
	0x19a0, 0x19bc, 0x19c6, 0x19cc, 0x19d8, 0x19ee, 0x19f2, 0x19f4, 0x1a0e, 0x1a1c, 0x1a38, 0x1a70,
	0x1a7e, 0x1ae0, 0x1afc, 0x1b08, 0x1b10, 0x1b1e, 0x1b20, 0x1b3c, 0x1b40, 0x1b78, 0x1b8c, 0x1b98,
	0x1bb0, 0x1bbe, 0x1bce, 0x1bdc, 0x1be2, 0x1be4, 0x1be8, 0x1bf6, 0x1c16, 0x1c26, 0x1c2c, 0x1c46,
	0x1c4c, 0x1c58, 0x1c6e, 0x1c86, 0x1c98, 0x1cb0, 0x1cbe, 0x1cce, 0x1cdc, 0x1ce2, 0x1ce4, 0x1ce8,
	0x1cf6, 0x1d06, 0x1d0c, 0x1d18, 0x1d30, 0x1d3e, 0x1d60, 0x1d7c, 0x1d8e, 0x1d9c, 0x1db8, 0x1dc4,
	0x1dc8, 0x1dd0, 0x1dde, 0x1de6, 0x1dec, 0x1dfa, 0x1e0a, 0x1e12, 0x1e14, 0x1e22, 0x1e24, 0x1e28,
	0x1e36, 0x1e42, 0x1e44, 0x1e50, 0x1e5e, 0x1e66, 0x1e6c, 0x1e82, 0x1e84, 0x1e88, 0x1e90, 0x1e9e,
	0x1ea0, 0x1ebc, 0x1ec6, 0x1ecc, 0x1ed8, 0x1eee, 0x1f1a, 0x1f2e, 0x1f32, 0x1f34, 0x1f4e, 0x1f5c,
	0x1f62, 0x1f64, 0x1f68, 0x1f76, 0x2048, 0x205e, 0x2082, 0x2084, 0x2090, 0x209e, 0x20a0, 0x20bc,
	0x20d8, 0x20f2, 0x20f4, 0x2108, 0x211e, 0x2120, 0x213c, 0x2140, 0x2178, 0x2186, 0x2198, 0x21b0,
	0x21be, 0x21e2, 0x21e4, 0x21e8, 0x21f6, 0x2204, 0x2210, 0x221e, 0x2220, 0x2278, 0x22f0, 0x2306,
	0x230c, 0x2330, 0x233e, 0x2360, 0x237c, 0x238e, 0x239c, 0x23b8, 0x23c2, 0x23c8, 0x23d0, 0x23e6,
	0x23ec, 0x241e, 0x2420, 0x243c, 0x24f0, 0x25e0, 0x2618, 0x263e, 0x2660, 0x267c, 0x26c0, 0x26f8,
	0x2738, 0x2770, 0x277e, 0x2782, 0x2784, 0x2790, 0x279e, 0x27a0, 0x27bc, 0x27c6, 0x27cc, 0x27d8,
	0x27ee, 0x2820, 0x283c, 0x2840, 0x2878, 0x28f0, 0x29e0, 0x2bc0, 0x2c18, 0x2c30, 0x2c3e, 0x2c60,
	0x2c7c, 0x2cc0, 0x2cf8, 0x2df0, 0x2e1c, 0x2e38, 0x2e70, 0x2e7e, 0x2ee0, 0x2efc, 0x2f04, 0x2f08,
	0x2f10, 0x2f20, 0x2f3c, 0x2f40, 0x2f78, 0x2f86, 0x2f8c, 0x2f98, 0x2fb0, 0x2fbe, 0x2fce, 0x2fdc,
	0x302e, 0x304e, 0x305c, 0x3062, 0x3068, 0x308e, 0x309c, 0x30b8, 0x30c2, 0x30c8, 0x30d0, 0x30de,
	0x30ec, 0x30fa, 0x310e, 0x3138, 0x3170, 0x317e, 0x3182, 0x3184, 0x3190, 0x319e, 0x31a0, 0x31bc,
	0x31c6, 0x31cc, 0x31d8, 0x31f2, 0x31f4, 0x320e, 0x321c, 0x3270, 0x327e, 0x32e0, 0x32fc, 0x3308,
	0x331e, 0x3320, 0x333c, 0x3340, 0x3378, 0x3386, 0x3398, 0x33b0, 0x33be, 0x33ce, 0x33dc, 0x33e2,
	0x33e4, 0x33e8, 0x33f6, 0x340e, 0x341c, 0x3438, 0x3470, 0x347e, 0x34e0, 0x34fc, 0x35c0, 0x35f8,
	0x3608, 0x3610, 0x361e, 0x3620, 0x363c, 0x3640, 0x3678, 0x36f0, 0x370c, 0x3718, 0x3730, 0x373e,
	0x3760, 0x377c, 0x379c, 0x37b8, 0x37c2, 0x37c4, 0x37c8, 0x37d0, 0x37de, 0x37e6, 0x37ec, 0x3816,
	0x3826, 0x382c, 0x3846, 0x384c, 0x3858, 0x386e, 0x3874, 0x3886, 0x3898, 0x38b0, 0x38be, 0x38ce,
	0x38dc, 0x38e2, 0x38e4, 0x38e8, 0x3906, 0x390c, 0x3930, 0x393e, 0x3960, 0x397c, 0x398e, 0x399c,
	0x39b8, 0x39c8, 0x39d0, 0x39de, 0x39e6, 0x39ec, 0x39fa, 0x3a06, 0x3a0c, 0x3a18, 0x3a30, 0x3a3e,
	0x3a60, 0x3a7c, 0x3ac0, 0x3af8, 0x3b0e, 0x3b1c, 0x3b38, 0x3b70, 0x3b7e, 0x3b88, 0x3b90, 0x3b9e,
	0x3ba0, 0x3bbc, 0x3bcc, 0x3bd8, 0x3bee, 0x3bf2, 0x3bf4, 0x3c12, 0x3c14, 0x3c22, 0x3c24, 0x3c28,
	0x3c36, 0x3c42, 0x3c48, 0x3c50, 0x3c5e, 0x3c66, 0x3c6c, 0x3c82, 0x3c84, 0x3c90, 0x3c9e, 0x3ca0,
	0x3cbc, 0x3cc6, 0x3ccc, 0x3cd8, 0x3cee, 0x3d02, 0x3d04, 0x3d08, 0x3d10, 0x3d1e, 0x3d20, 0x3d3c,
	0x3d40, 0x3d78, 0x3d86, 0x3d8c, 0x3d98, 0x3db0, 0x3dbe, 0x3dce, 0x3ddc, 0x3de4, 0x3de8, 0x3df6,
	0x3e1a, 0x3e2e, 0x3e32, 0x3e34, 0x3e4e, 0x3e5c, 0x3e62, 0x3e64, 0x3e68, 0x3e76, 0x3e8e, 0x3e9c,
	0x3eb8, 0x3ec2, 0x3ec4, 0x3ec8, 0x3ed0, 0x3ede, 0x3ee6, 0x3eec, 0x3f26, 0x3f2c, 0x3f3a, 0x3f46,
	0x3f4c, 0x3f58, 0x3f6e, 0x3f72, 0x3f74, 0x4082, 0x409e, 0x40a0, 0x40bc, 0x4104, 0x4108, 0x4110,
	0x411e, 0x4120, 0x413c, 0x4140, 0x4178, 0x418c, 0x4198, 0x41b0, 0x41be, 0x41e2, 0x41e4, 0x41e8,
	0x4208, 0x4210, 0x421e, 0x4220, 0x423c, 0x4240, 0x4278, 0x42f0, 0x4306, 0x430c, 0x4318, 0x4330,
	0x433e, 0x4360, 0x437c, 0x438e, 0x43c2, 0x43c4, 0x43c8, 0x43d0, 0x43e6, 0x43ec, 0x4408, 0x4410,
	0x441e, 0x4420, 0x443c, 0x4440, 0x4478, 0x44f0, 0x45e0, 0x460c, 0x4618, 0x4630, 0x463e, 0x4660,
	0x467c, 0x46c0, 0x46f8, 0x471c, 0x4738, 0x4770, 0x477e, 0x4782, 0x4784, 0x4788, 0x4790, 0x47a0,
	0x47bc, 0x47c6, 0x47cc, 0x47d8, 0x47ee, 0x4810, 0x4820, 0x483c, 0x4840, 0x4878, 0x48f0, 0x49e0,
	0x4bc0, 0x4c30, 0x4c3e, 0x4c60, 0x4c7c, 0x4cc0, 0x4cf8, 0x4df0, 0x4e38, 0x4e70, 0x4e7e, 0x4ee0,
	0x4efc, 0x4f04, 0x4f08, 0x4f10, 0x4f1e, 0x4f20, 0x4f3c, 0x4f40, 0x4f78, 0x4f86, 0x4f8c, 0x4f98,
	0x4fb0, 0x4fce, 0x4fdc, 0x5020, 0x5040, 0x5078, 0x50f0, 0x51e0, 0x53c0, 0x5860, 0x587c, 0x58c0,
	0x58f8, 0x59f0, 0x5be0, 0x5c70, 0x5c7e, 0x5ce0, 0x5cfc, 0x5dc0, 0x5df8, 0x5e08, 0x5e10, 0x5e20,
	0x5e40, 0x5e78, 0x5ef0, 0x5f0c, 0x5f18, 0x5f30, 0x5f60, 0x5f7c, 0x5f8e, 0x5f9c, 0x5fb8, 0x604e,
	0x605c, 0x608e, 0x609c, 0x60b8, 0x60c2, 0x60c4, 0x60c8, 0x60de, 0x610e, 0x611c, 0x6138, 0x6170,
	0x617e, 0x6184, 0x6188, 0x6190, 0x619e, 0x61a0, 0x61bc, 0x61c6, 0x61cc, 0x61d8, 0x61f2, 0x61f4,
	0x620e, 0x621c, 0x6238, 0x6270, 0x627e, 0x62e0, 0x62fc, 0x6304, 0x6308, 0x6310, 0x631e, 0x6320,
	0x633c, 0x6340, 0x6378, 0x6386, 0x638c, 0x6398, 0x63b0, 0x63be, 0x63ce, 0x63dc, 0x63e2, 0x63e4,
	0x63e8, 0x63f6, 0x640e, 0x641c, 0x6438, 0x6470, 0x647e, 0x64e0, 0x64fc, 0x65c0, 0x65f8, 0x6610,
	0x661e, 0x6620, 0x663c, 0x6640, 0x6678, 0x66f0, 0x6718, 0x6730, 0x673e, 0x6760, 0x677c, 0x678e,
	0x679c, 0x67b8, 0x67c2, 0x67c4, 0x67c8, 0x67d0, 0x67de, 0x67e6, 0x67ec, 0x681c, 0x6838, 0x6870,
	0x68e0, 0x68fc, 0x69c0, 0x69f8, 0x6bf0, 0x6c10, 0x6c1e, 0x6c20, 0x6c3c, 0x6c40, 0x6c78, 0x6cf0,
	0x6de0, 0x6e18, 0x6e30, 0x6e3e, 0x6e60, 0x6e7c, 0x6ec0, 0x6ef8, 0x6f1c, 0x6f38, 0x6f70, 0x6f7e,
	0x6f84, 0x6f88, 0x6f90, 0x6f9e, 0x6fa0, 0x6fbc, 0x6fc6, 0x6fcc, 0x6fd8, 0x7026, 0x702c, 0x7046,
	0x704c, 0x7058, 0x706e, 0x7086, 0x708c, 0x7098, 0x70b0, 0x70be, 0x70ce, 0x70dc, 0x70e8, 0x7106,
	0x710c, 0x7118, 0x7130, 0x713e, 0x7160, 0x717c, 0x718e, 0x719c, 0x71b8, 0x71c2, 0x71c4, 0x71c8,
	0x71d0, 0x71de, 0x71e6, 0x71ec, 0x71fa, 0x7206, 0x720c, 0x7218, 0x7230, 0x723e, 0x7260, 0x727c,
	0x72c0, 0x72f8, 0x730e, 0x731c, 0x7338, 0x7370, 0x737e, 0x7388, 0x7390, 0x739e, 0x73a0, 0x73bc,
	0x73cc, 0x73d8, 0x73ee, 0x73f2, 0x73f4, 0x740c, 0x7418, 0x7430, 0x743e, 0x7460, 0x747c, 0x74c0,
	0x74f8, 0x75f0, 0x760e, 0x761c, 0x7638, 0x7670, 0x767e, 0x76e0, 0x76fc, 0x7708, 0x7710, 0x771e,
	0x7720, 0x773c, 0x7740, 0x7778, 0x7798, 0x77b0, 0x77be, 0x77dc, 0x77e2, 0x77e4, 0x77e8, 0x7822,
	0x7824, 0x7828, 0x7836, 0x7842, 0x7844, 0x7848, 0x7850, 0x785e, 0x7866, 0x786c, 0x7882, 0x7884,
	0x7888, 0x7890, 0x789e, 0x78a0, 0x78bc, 0x78c6, 0x78cc, 0x78d8, 0x78ee, 0x78f2, 0x78f4, 0x7902,
	0x7904, 0x7908, 0x7910, 0x791e, 0x7920, 0x793c, 0x7940, 0x7978, 0x7986, 0x798c, 0x7998, 0x79b0,
	0x79be, 0x79ce, 0x79dc, 0x79e2, 0x79e4, 0x79e8, 0x79f6, 0x7a04, 0x7a08, 0x7a10, 0x7a1e, 0x7a20,
	0x7a3c, 0x7a40, 0x7a78, 0x7af0, 0x7b06, 0x7b0c, 0x7b18, 0x7b30, 0x7b3e, 0x7b60, 0x7b7c, 0x7b8e,
	0x7b9c, 0x7bb8, 0x7bc4, 0x7bc8, 0x7bd0, 0x7bde, 0x7be6, 0x7bec, 0x7c2e, 0x7c32, 0x7c34, 0x7c4e,
	0x7c5c, 0x7c62, 0x7c64, 0x7c68, 0x7c76, 0x7c8e, 0x7c9c, 0x7cb8, 0x7cc2, 0x7cc4, 0x7cc8, 0x7cd0,
	0x7cde, 0x7ce6, 0x7cec, 0x7d0e, 0x7d1c, 0x7d38, 0x7d70, 0x7d82, 0x7d84, 0x7d88, 0x7d90, 0x7d9e,
	0x7da0, 0x7dbc, 0x7dc6, 0x7dcc, 0x7dd8, 0x7dee, 0x7e26, 0x7e2c, 0x7e3a, 0x7e46, 0x7e4c, 0x7e58,
	0x7e6e, 0x7e72, 0x7e74, 0x7e86, 0x7e8c, 0x7e98, 0x7eb0, 0x7ece, 0x7edc, 0x7ee2, 0x7ee4, 0x7ee8,
	0x7ef6, 0x813a, 0x8172, 0x8174, 0x8216, 0x8226, 0x823a, 0x824c, 0x8258, 0x826e, 0x8272, 0x8274,
	0x8298, 0x82be, 0x82e2, 0x82e4, 0x82e8, 0x82f6, 0x835e, 0x837a, 0x83ae, 0x83d6, 0x8416, 0x8426,
	0x842c, 0x843a, 0x8446, 0x8458, 0x846e, 0x8472, 0x8474, 0x8486, 0x84b0, 0x84be, 0x84ce, 0x84dc,
	0x84e2, 0x84e4, 0x84e8, 0x84f6, 0x8506, 0x850c, 0x8518, 0x8530, 0x853e, 0x8560, 0x857c, 0x858e,
	0x859c, 0x85b8, 0x85c2, 0x85c4, 0x85c8, 0x85d0, 0x85de, 0x85e6, 0x85ec, 0x85fa, 0x8612, 0x8614,
	0x8622, 0x8628, 0x8636, 0x8642, 0x8650, 0x865e, 0x867a, 0x8682, 0x8684, 0x8688, 0x8690, 0x869e,
	0x86a0, 0x86bc, 0x86c6, 0x86cc, 0x86d8, 0x86ee, 0x86f2, 0x86f4, 0x872e, 0x874e, 0x875c, 0x8796,
	0x87a6, 0x87ac, 0x87d2, 0x87d4, 0x8826, 0x882c, 0x883a, 0x8846, 0x884c, 0x8858, 0x886e, 0x8872,
	0x8874, 0x8886, 0x8898, 0x88b0, 0x88be, 0x88ce, 0x88dc, 0x88e2, 0x88e4, 0x88e8, 0x88f6, 0x890c,
	0x8930, 0x893e, 0x8960, 0x897c, 0x898e, 0x89b8, 0x89c2, 0x89c8, 0x89d0, 0x89de, 0x89e6, 0x89ec,
	0x89fa, 0x8a18, 0x8a30, 0x8a3e, 0x8a60, 0x8a7c, 0x8ac0, 0x8af8, 0x8b1c, 0x8b38, 0x8b70, 0x8b7e,
	0x8b82, 0x8b84, 0x8b88, 0x8b90, 0x8b9e, 0x8ba0, 0x8bbc, 0x8bc6, 0x8bcc, 0x8bd8, 0x8bee, 0x8bf2,
	0x8bf4, 0x8c22, 0x8c24, 0x8c28, 0x8c36, 0x8c42, 0x8c48, 0x8c50, 0x8c5e, 0x8c66, 0x8c7a, 0x8c82,
	0x8c84, 0x8c90, 0x8c9e, 0x8ca0, 0x8cbc, 0x8ccc, 0x8cf2, 0x8cf4, 0x8d04, 0x8d08, 0x8d10, 0x8d1e,
	0x8d20, 0x8d3c, 0x8d40, 0x8d78, 0x8d86, 0x8d98, 0x8dce, 0x8de2, 0x8de4, 0x8de8, 0x8e2e, 0x8e32,
	0x8e34, 0x8e4e, 0x8e5c, 0x8e62, 0x8e64, 0x8e68, 0x8e8e, 0x8e9c, 0x8eb8, 0x8ec2, 0x8ec4, 0x8ec8,
	0x8ed0, 0x8efa, 0x8f16, 0x8f26, 0x8f2c, 0x8f46, 0x8f4c, 0x8f58, 0x8f6e, 0x8f8a, 0x8f92, 0x8f94,
	0x8fa2, 0x8fa4, 0x8fa8, 0x8fb6, 0x902c, 0x903a, 0x9046, 0x904c, 0x9058, 0x9072, 0x9074, 0x9086,
	0x9098, 0x90b0, 0x90be, 0x90ce, 0x90dc, 0x90e2, 0x90e8, 0x90f6, 0x9106, 0x910c, 0x9130, 0x913e,
	0x9160, 0x917c, 0x918e, 0x919c, 0x91b8, 0x91c2, 0x91c8, 0x91d0, 0x91de, 0x91e6, 0x91ec, 0x91fa,
	0x9218, 0x923e, 0x9260, 0x927c, 0x92c0, 0x92f8, 0x9338, 0x9370, 0x937e, 0x9382, 0x9384, 0x9390,
	0x939e, 0x93a0, 0x93bc, 0x93c6, 0x93cc, 0x93d8, 0x93ee, 0x93f2, 0x93f4, 0x9430, 0x943e, 0x9460,
	0x947c, 0x94c0, 0x94f8, 0x95f0, 0x9638, 0x9670, 0x967e, 0x96e0, 0x96fc, 0x9702, 0x9704, 0x9708,
	0x9710, 0x9720, 0x973c, 0x9740, 0x9778, 0x9786, 0x978c, 0x9798, 0x97b0, 0x97be, 0x97ce, 0x97dc,
	0x97e2, 0x97e4, 0x97e8, 0x9822, 0x9824, 0x9842, 0x9848, 0x9850, 0x985e, 0x9866, 0x987a, 0x9882,
	0x9884, 0x9890, 0x989e, 0x98a0, 0x98bc, 0x98cc, 0x98f2, 0x98f4, 0x9902, 0x9908, 0x991e, 0x9920,
	0x993c, 0x9940, 0x9978, 0x9986, 0x9998, 0x99ce, 0x99e2, 0x99e4, 0x99e8, 0x9a08, 0x9a10, 0x9a1e,
	0x9a20, 0x9a3c, 0x9a40, 0x9a78, 0x9af0, 0x9b18, 0x9b3e, 0x9b60, 0x9b9c, 0x9bc2, 0x9bc4, 0x9bc8,
	0x9bd0, 0x9be6, 0x9c2e, 0x9c34, 0x9c4e, 0x9c5c, 0x9c62, 0x9c64, 0x9c68, 0x9c8e, 0x9c9c, 0x9cb8,
	0x9cc2, 0x9cc8, 0x9cd0, 0x9ce6, 0x9cfa, 0x9d0e, 0x9d1c, 0x9d38, 0x9d70, 0x9d7e, 0x9d82, 0x9d84,
	0x9d88, 0x9d90, 0x9da0, 0x9dcc, 0x9df2, 0x9df4, 0x9e16, 0x9e26, 0x9e2c, 0x9e46, 0x9e4c, 0x9e58,
	0x9e74, 0x9e86, 0x9e8c, 0x9e98, 0x9eb0, 0x9ebe, 0x9ece, 0x9ee2, 0x9ee4, 0x9ee8, 0x9f0a, 0x9f12,
	0x9f14, 0x9f22, 0x9f24, 0x9f28, 0x9f42, 0x9f44, 0x9f48, 0x9f50, 0x9f5e, 0x9f6c, 0x9f9a, 0x9fae,
	0x9fb2, 0x9fb4, 0xa046, 0xa04c, 0xa072, 0xa074, 0xa086, 0xa08c, 0xa098, 0xa0b0, 0xa0be, 0xa0e2,
	0xa0e4, 0xa0e8, 0xa0f6, 0xa106, 0xa10c, 0xa118, 0xa130, 0xa13e, 0xa160, 0xa17c, 0xa18e, 0xa19c,
	0xa1b8, 0xa1c2, 0xa1c4, 0xa1c8, 0xa1d0, 0xa1de, 0xa1e6, 0xa1ec, 0xa218, 0xa230, 0xa23e, 0xa260,
	0xa27c, 0xa2c0, 0xa2f8, 0xa31c, 0xa338, 0xa370, 0xa37e, 0xa382, 0xa384, 0xa388, 0xa390, 0xa39e,
	0xa3a0, 0xa3bc, 0xa3c6, 0xa3cc, 0xa3d8, 0xa3ee, 0xa3f2, 0xa3f4, 0xa418, 0xa430, 0xa43e, 0xa460,
	0xa47c, 0xa4c0, 0xa4f8, 0xa5f0, 0xa61c, 0xa638, 0xa670, 0xa67e, 0xa6e0, 0xa6fc, 0xa702, 0xa704,
	0xa708, 0xa710, 0xa71e, 0xa720, 0xa73c, 0xa740, 0xa778, 0xa786, 0xa78c, 0xa798, 0xa7b0, 0xa7be,
	0xa7ce, 0xa7dc, 0xa7e2, 0xa7e4, 0xa7e8, 0xa830, 0xa860, 0xa87c, 0xa8c0, 0xa8f8, 0xa9f0, 0xabe0,
	0xac70, 0xac7e, 0xace0, 0xacfc, 0xadc0, 0xadf8, 0xae04, 0xae08, 0xae10, 0xae20, 0xae3c, 0xae40,
	0xae78, 0xaef0, 0xaf06, 0xaf0c, 0xaf18, 0xaf30, 0xaf3e, 0xaf60, 0xaf7c, 0xaf8e, 0xaf9c, 0xafb8,
	0xafc4, 0xafc8, 0xafd0, 0xafde, 0xb042, 0xb05e, 0xb07a, 0xb082, 0xb084, 0xb088, 0xb090, 0xb09e,
	0xb0a0, 0xb0bc, 0xb0cc, 0xb0f2, 0xb0f4, 0xb102, 0xb104, 0xb108, 0xb110, 0xb11e, 0xb120, 0xb13c,
	0xb140, 0xb178, 0xb186, 0xb198, 0xb1ce, 0xb1e2, 0xb1e4, 0xb1e8, 0xb204, 0xb208, 0xb210, 0xb21e,
	0xb220, 0xb23c, 0xb240, 0xb278, 0xb2f0, 0xb30c, 0xb33e, 0xb360, 0xb39c, 0xb3c2, 0xb3c4, 0xb3c8,
	0xb3d0, 0xb3e6, 0xb410, 0xb41e, 0xb420, 0xb43c, 0xb440, 0xb478, 0xb4f0, 0xb5e0, 0xb618, 0xb660,
	0xb67c, 0xb6c0, 0xb738, 0xb782, 0xb784, 0xb788, 0xb790, 0xb79e, 0xb7a0, 0xb7cc, 0xb82e, 0xb84e,
	0xb85c, 0xb88e, 0xb89c, 0xb8b8, 0xb8c2, 0xb8c4, 0xb8c8, 0xb8d0, 0xb8e6, 0xb8fa, 0xb90e, 0xb91c,
	0xb938, 0xb970, 0xb97e, 0xb982, 0xb984, 0xb988, 0xb990, 0xb99e, 0xb9a0, 0xb9cc, 0xb9f2, 0xb9f4,
	0xba0e, 0xba1c, 0xba38, 0xba70, 0xba7e, 0xbae0, 0xbafc, 0xbb08, 0xbb10, 0xbb20, 0xbb3c, 0xbb40,
	0xbb98, 0xbbce, 0xbbe2, 0xbbe4, 0xbbe8, 0xbc16, 0xbc26, 0xbc2c, 0xbc46, 0xbc4c, 0xbc58, 0xbc72,
	0xbc74, 0xbc86, 0xbc8c, 0xbc98, 0xbcb0, 0xbcbe, 0xbcce, 0xbce2, 0xbce4, 0xbce8, 0xbd06, 0xbd0c,
	0xbd18, 0xbd30, 0xbd3e, 0xbd60, 0xbd7c, 0xbd9c, 0xbdc2, 0xbdc4, 0xbdc8, 0xbdd0, 0xbde6, 0xbdfa,
	0xbe12, 0xbe14, 0xbe22, 0xbe24, 0xbe28, 0xbe42, 0xbe44, 0xbe48, 0xbe50, 0xbe5e, 0xbe66, 0xbe82,
	0xbe84, 0xbe88, 0xbe90, 0xbe9e, 0xbea0, 0xbebc, 0xbecc, 0xbef4, 0xbf1a, 0xbf2e, 0xbf32, 0xbf34,
	0xbf4e, 0xbf5c, 0xbf62, 0xbf64, 0xbf68, 0xc09a, 0xc0b2, 0xc0b4, 0xc11a, 0xc132, 0xc134, 0xc162,
	0xc164, 0xc168, 0xc176, 0xc1ba, 0xc21a, 0xc232, 0xc234, 0xc24e, 0xc25c, 0xc262, 0xc264, 0xc268,
	0xc276, 0xc28e, 0xc2c2, 0xc2c4, 0xc2c8, 0xc2d0, 0xc2de, 0xc2e6, 0xc2ec, 0xc2fa, 0xc316, 0xc326,
	0xc33a, 0xc346, 0xc34c, 0xc372, 0xc374, 0xc41a, 0xc42e, 0xc432, 0xc434, 0xc44e, 0xc45c, 0xc462,
	0xc464, 0xc468, 0xc476, 0xc48e, 0xc49c, 0xc4b8, 0xc4c2, 0xc4c8, 0xc4d0, 0xc4de, 0xc4e6, 0xc4ec,
	0xc4fa, 0xc51c, 0xc538, 0xc570, 0xc57e, 0xc582, 0xc584, 0xc588, 0xc590, 0xc59e, 0xc5a0, 0xc5bc,
	0xc5c6, 0xc5cc, 0xc5d8, 0xc5ee, 0xc5f2, 0xc5f4, 0xc616, 0xc626, 0xc62c, 0xc63a, 0xc646, 0xc64c,
	0xc658, 0xc66e, 0xc672, 0xc674, 0xc686, 0xc68c, 0xc698, 0xc6b0, 0xc6be, 0xc6ce, 0xc6dc, 0xc6e2,
	0xc6e4, 0xc6e8, 0xc712, 0xc714, 0xc722, 0xc728, 0xc736, 0xc742, 0xc744, 0xc748, 0xc750, 0xc75e,
	0xc766, 0xc76c, 0xc77a, 0xc7ae, 0xc7d6, 0xc7ea, 0xc81a, 0xc82e, 0xc832, 0xc834, 0xc84e, 0xc85c,
	0xc862, 0xc864, 0xc868, 0xc876, 0xc88e, 0xc89c, 0xc8b8, 0xc8c2, 0xc8c8, 0xc8d0, 0xc8de, 0xc8e6,
	0xc8ec, 0xc8fa, 0xc90e, 0xc938, 0xc970, 0xc97e, 0xc982, 0xc984, 0xc990, 0xc99e, 0xc9a0, 0xc9bc,
	0xc9c6, 0xc9cc, 0xc9d8, 0xc9ee, 0xc9f2, 0xc9f4, 0xca38, 0xca70, 0xca7e, 0xcae0, 0xcafc, 0xcb02,
	0xcb04, 0xcb08, 0xcb10, 0xcb20, 0xcb3c, 0xcb40, 0xcb78, 0xcb86, 0xcb8c, 0xcb98, 0xcbb0, 0xcbbe,
	0xcbce, 0xcbdc, 0xcbe2, 0xcbe4, 0xcbe8, 0xcbf6, 0xcc16, 0xcc26, 0xcc2c, 0xcc3a, 0xcc46, 0xcc58,
	0xcc72, 0xcc74, 0xcc86, 0xccb0, 0xccbe, 0xccce, 0xcce2, 0xcce4, 0xcce8, 0xcd06, 0xcd0c, 0xcd18,
	0xcd30, 0xcd3e, 0xcd60, 0xcd7c, 0xcd9c, 0xcdc2, 0xcdc4, 0xcdc8, 0xcdd0, 0xcdde, 0xcde6, 0xcdfa,
	0xce22, 0xce28, 0xce42, 0xce50, 0xce5e, 0xce66, 0xce7a, 0xce82, 0xce84, 0xce88, 0xce90, 0xce9e,
	0xcea0, 0xcebc, 0xcecc, 0xcef2, 0xcef4, 0xcf2e, 0xcf32, 0xcf34, 0xcf4e, 0xcf5c, 0xcf62, 0xcf64,
	0xcf68, 0xcf96, 0xcfa6, 0xcfac, 0xcfca, 0xcfd2, 0xcfd4, 0xd02e, 0xd032, 0xd034, 0xd04e, 0xd05c,
	0xd062, 0xd064, 0xd068, 0xd076, 0xd08e, 0xd09c, 0xd0b8, 0xd0c2, 0xd0c4, 0xd0c8, 0xd0d0, 0xd0de,
	0xd0e6, 0xd0ec, 0xd0fa, 0xd11c, 0xd138, 0xd170, 0xd17e, 0xd182, 0xd184, 0xd188, 0xd190, 0xd19e,
	0xd1a0, 0xd1bc, 0xd1c6, 0xd1cc, 0xd1d8, 0xd1ee, 0xd1f2, 0xd1f4, 0xd21c, 0xd238, 0xd270, 0xd27e,
	0xd2e0, 0xd2fc, 0xd302, 0xd304, 0xd308, 0xd310, 0xd31e, 0xd320, 0xd33c, 0xd340, 0xd378, 0xd386,
	0xd38c, 0xd398, 0xd3b0, 0xd3be, 0xd3ce, 0xd3dc, 0xd3e2, 0xd3e4, 0xd3e8, 0xd3f6, 0xd470, 0xd47e,
	0xd4e0, 0xd4fc, 0xd5c0, 0xd5f8, 0xd604, 0xd608, 0xd610, 0xd620, 0xd640, 0xd678, 0xd6f0, 0xd706,
	0xd70c, 0xd718, 0xd730, 0xd73e, 0xd760, 0xd77c, 0xd78e, 0xd79c, 0xd7b8, 0xd7c2, 0xd7c4, 0xd7c8,
	0xd7d0, 0xd7de, 0xd7e6, 0xd7ec, 0xd826, 0xd82c, 0xd83a, 0xd846, 0xd84c, 0xd858, 0xd872, 0xd874,
	0xd886, 0xd88c, 0xd898, 0xd8b0, 0xd8be, 0xd8ce, 0xd8e2, 0xd8e4, 0xd8e8, 0xd8f6, 0xd90c, 0xd918,
	0xd930, 0xd93e, 0xd960, 0xd97c, 0xd99c, 0xd9c2, 0xd9c4, 0xd9c8, 0xd9d0, 0xd9e6, 0xd9fa, 0xda0c,
	0xda18, 0xda30, 0xda3e, 0xda60, 0xda7c, 0xdac0, 0xdaf8, 0xdb38, 0xdb82, 0xdb84, 0xdb88, 0xdb90,
	0xdb9e, 0xdba0, 0xdbcc, 0xdbf2, 0xdbf4, 0xdc22, 0xdc42, 0xdc44, 0xdc48, 0xdc50, 0xdc5e, 0xdc66,
	0xdc7a, 0xdc82, 0xdc84, 0xdc88, 0xdc90, 0xdc9e, 0xdca0, 0xdcbc, 0xdccc, 0xdcf2, 0xdcf4, 0xdd04,
	0xdd08, 0xdd10, 0xdd1e, 0xdd20, 0xdd3c, 0xdd40, 0xdd78, 0xdd86, 0xdd98, 0xddce, 0xdde2, 0xdde4,
	0xdde8, 0xde2e, 0xde32, 0xde34, 0xde4e, 0xde5c, 0xde62, 0xde64, 0xde68, 0xde8e, 0xde9c, 0xdeb8,
	0xdec2, 0xdec4, 0xdec8, 0xded0, 0xdee6, 0xdefa, 0xdf16, 0xdf26, 0xdf2c, 0xdf46, 0xdf4c, 0xdf58,
	0xdf72, 0xdf74, 0xdf8a, 0xdf92, 0xdf94, 0xdfa2, 0xdfa4, 0xdfa8, 0xe08a, 0xe092, 0xe094, 0xe0a2,
	0xe0a4, 0xe0a8, 0xe0b6, 0xe0da, 0xe10a, 0xe112, 0xe114, 0xe122, 0xe124, 0xe128, 0xe136, 0xe142,
	0xe144, 0xe148, 0xe150, 0xe166, 0xe16c, 0xe17a, 0xe19a, 0xe1b2, 0xe1b4, 0xe20a, 0xe212, 0xe214,
	0xe222, 0xe224, 0xe228, 0xe236, 0xe242, 0xe248, 0xe250, 0xe25e, 0xe266, 0xe26c, 0xe27a, 0xe282,
	0xe284, 0xe288, 0xe290, 0xe2a0, 0xe2bc, 0xe2c6, 0xe2cc, 0xe2d8, 0xe2ee, 0xe2f2, 0xe2f4, 0xe31a,
	0xe332, 0xe334, 0xe35c, 0xe362, 0xe364, 0xe368, 0xe3ba, 0xe40a, 0xe412, 0xe414, 0xe422, 0xe428,
	0xe436, 0xe442, 0xe448, 0xe450, 0xe45e, 0xe466, 0xe46c, 0xe47a, 0xe482, 0xe484, 0xe490, 0xe49e,
	0xe4a0, 0xe4bc, 0xe4c6, 0xe4cc, 0xe4d8, 0xe4ee, 0xe4f2, 0xe4f4, 0xe502, 0xe504, 0xe508, 0xe510,
	0xe51e, 0xe520, 0xe53c, 0xe540, 0xe578, 0xe586, 0xe58c, 0xe598, 0xe5b0, 0xe5be, 0xe5ce, 0xe5dc,
	0xe5e2, 0xe5e4, 0xe5e8, 0xe5f6, 0xe61a, 0xe62e, 0xe632, 0xe634, 0xe64e, 0xe65c, 0xe662, 0xe668,
	0xe68e, 0xe69c, 0xe6b8, 0xe6c2, 0xe6c4, 0xe6c8, 0xe6d0, 0xe6e6, 0xe6fa, 0xe716, 0xe726, 0xe72c,
	0xe73a, 0xe746, 0xe74c, 0xe758, 0xe772, 0xe774, 0xe792, 0xe794, 0xe7a2, 0xe7a4, 0xe7a8, 0xe7b6,
	0xe812, 0xe814, 0xe822, 0xe824, 0xe828, 0xe836, 0xe842, 0xe844, 0xe848, 0xe850, 0xe85e, 0xe866,
	0xe86c, 0xe87a, 0xe882, 0xe884, 0xe888, 0xe890, 0xe89e, 0xe8a0, 0xe8bc, 0xe8c6, 0xe8cc, 0xe8d8,
	0xe8ee, 0xe8f2, 0xe8f4, 0xe902, 0xe904, 0xe908, 0xe910, 0xe920, 0xe93c, 0xe940, 0xe978, 0xe986,
	0xe98c, 0xe998, 0xe9b0, 0xe9be, 0xe9ce, 0xe9dc, 0xe9e2, 0xe9e4, 0xe9e8, 0xe9f6, 0xea04, 0xea08,
	0xea10, 0xea20, 0xea40, 0xea78, 0xeaf0, 0xeb06, 0xeb0c, 0xeb18, 0xeb30, 0xeb3e, 0xeb60, 0xeb7c,
	0xeb8e, 0xeb9c, 0xebb8, 0xebc2, 0xebc4, 0xebc8, 0xebd0, 0xebde, 0xebe6, 0xebec, 0xec1a, 0xec2e,
	0xec32, 0xec34, 0xec4e, 0xec5c, 0xec62, 0xec64, 0xec68, 0xec8e, 0xec9c, 0xecb8, 0xecc2, 0xecc4,
	0xecc8, 0xecd0, 0xece6, 0xecfa, 0xed0e, 0xed1c, 0xed38, 0xed70, 0xed7e, 0xed82, 0xed84, 0xed88,
	0xed90, 0xed9e, 0xeda0, 0xedcc, 0xedf2, 0xedf4, 0xee16, 0xee26, 0xee2c, 0xee3a, 0xee46, 0xee4c,
	0xee58, 0xee6e, 0xee72, 0xee74, 0xee86, 0xee8c, 0xee98, 0xeeb0, 0xeebe, 0xeece, 0xeedc, 0xeee2,
	0xeee4, 0xeee8, 0xef12, 0xef22, 0xef24, 0xef28, 0xef36, 0xef42, 0xef44, 0xef48, 0xef50, 0xef5e,
	0xef66, 0xef6c, 0xef7a, 0xefae, 0xefb2, 0xefb4, 0xefd6, 0xf096, 0xf0a6, 0xf0ac, 0xf0ba, 0xf0ca,
	0xf0d2, 0xf0d4, 0xf116, 0xf126, 0xf12c, 0xf13a, 0xf146, 0xf14c, 0xf158, 0xf16e, 0xf172, 0xf174,
	0xf18a, 0xf192, 0xf194, 0xf1a2, 0xf1a4, 0xf1a8, 0xf1da, 0xf216, 0xf226, 0xf22c, 0xf23a, 0xf246,
	0xf258, 0xf26e, 0xf272, 0xf274, 0xf286, 0xf28c, 0xf298, 0xf2b0, 0xf2be, 0xf2ce, 0xf2dc, 0xf2e2,
	0xf2e4, 0xf2e8, 0xf2f6, 0xf30a, 0xf312, 0xf314, 0xf322, 0xf328, 0xf342, 0xf344, 0xf348, 0xf350,
	0xf35e, 0xf366, 0xf37a, 0xf39a, 0xf3ae, 0xf3b2, 0xf3b4, 0xf416, 0xf426, 0xf42c, 0xf43a, 0xf446,
	0xf44c, 0xf458, 0xf46e, 0xf472, 0xf474, 0xf486, 0xf48c, 0xf498, 0xf4b0, 0xf4be, 0xf4ce, 0xf4dc,
	0xf4e2, 0xf4e4, 0xf4e8, 0xf4f6, 0xf506, 0xf50c, 0xf518, 0xf530, 0xf53e, 0xf560, 0xf57c, 0xf58e,
	0xf59c, 0xf5b8, 0xf5c2, 0xf5c4, 0xf5c8, 0xf5d0, 0xf5de, 0xf5e6, 0xf5ec, 0xf5fa, 0xf60a, 0xf612,
	0xf614, 0xf622, 0xf624, 0xf628, 0xf636, 0xf642, 0xf644, 0xf648, 0xf650, 0xf65e, 0xf666, 0xf67a,
	0xf682, 0xf684, 0xf688, 0xf690, 0xf69e, 0xf6a0, 0xf6bc, 0xf6cc, 0xf6f2, 0xf6f4, 0xf71a, 0xf72e,
	0xf732, 0xf734, 0xf74e, 0xf75c, 0xf762, 0xf764, 0xf768, 0xf776, 0xf796, 0xf7a6, 0xf7ac, 0xf7ba,
	0xf7d2, 0xf7d4, 0xf89a, 0xf8ae, 0xf8b2, 0xf8b4, 0xf8d6, 0xf8ea, 0xf91a, 0xf92e, 0xf932, 0xf934,
	0xf94e, 0xf95c, 0xf962, 0xf964, 0xf968, 0xf976, 0xf996, 0xf9a6, 0xf9ac, 0xf9ba, 0xf9ca, 0xf9d2,
	0xf9d4, 0xfa1a, 0xfa2e, 0xfa32, 0xfa34, 0xfa4e, 0xfa5c, 0xfa62, 0xfa64, 0xfa68, 0xfa76, 0xfa8e,
	0xfa9c, 0xfab8, 0xfac2, 0xfac4, 0xfac8, 0xfad0, 0xfade, 0xfae6, 0xfaec, 0xfb16, 0xfb26, 0xfb2c,
	0xfb3a, 0xfb46, 0xfb4c, 0xfb58, 0xfb6e, 0xfb72, 0xfb74, 0xfb8a, 0xfb92, 0xfb94, 0xfba2, 0xfba4,
	0xfba8, 0xfbb6, 0xfbda
};

/**
* This table contains to codewords for all symbols.
*/
static constexpr const std::array<uint16_t, 2787> CODEWORD_TABLE = {
	2627, 1819, 2622, 2621, 1813, 1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865, 861, 859, 2511,
	873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844, 1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815,
	814, 813, 812, 2484, 817, 816, 1745, 1744, 1742, 1746, 2655, 2637, 2635, 2626, 2625, 2623, 2628, 1820, 2752,
	2739, 2737, 2728, 2727, 2725, 2730, 2785, 2783, 2778, 2777, 2775, 2780, 787, 781, 747, 739, 736, 2413, 754, 752,
	1719, 692, 689, 681, 2371, 678, 2369, 700, 697, 694, 703, 1688, 1686, 642, 638, 2343, 631, 2341, 627, 2338, 651,
	646, 643, 2345, 654, 652, 1652, 1650, 1647, 1654, 601, 599, 2322, 596, 2321, 594, 2319, 2317, 611, 610, 608, 606,
	2324, 603, 2323, 615, 614, 612, 1617, 1616, 1614, 1612, 616, 1619, 1618, 2575, 2538, 2536, 905, 901, 898, 909,
	2509, 2507, 2504, 870, 867, 864, 860, 2512, 875, 872, 1781, 2490, 2489, 2487, 2485, 1748, 836, 834, 832, 830,
	2494, 827, 2492, 843, 841, 839, 845, 1765, 1763, 2701, 2676, 2674, 2653, 2648, 2656, 2634, 2633, 2631, 2629,
	1821, 2638, 2636, 2770, 2763, 2761, 2750, 2745, 2753, 2736, 2735, 2733, 2731, 1848, 2740, 2738, 2786, 2784, 591,
	588, 576, 569, 566, 2296, 1590, 537, 534, 526, 2276, 522, 2274, 545, 542, 539, 548, 1572, 1570, 481, 2245, 466,
	2242, 462, 2239, 492, 485, 482, 2249, 496, 494, 1534, 1531, 1528, 1538, 413, 2196, 406, 2191, 2188, 425, 419,
	2202, 415, 2199, 432, 430, 427, 1472, 1467, 1464, 433, 1476, 1474, 368, 367, 2160, 365, 2159, 362, 2157, 2155,
	2152, 378, 377, 375, 2166, 372, 2165, 369, 2162, 383, 381, 379, 2168, 1419, 1418, 1416, 1414, 385, 1411, 384,
	1423, 1422, 1420, 1424, 2461, 802, 2441, 2439, 790, 786, 783, 794, 2409, 2406, 2403, 750, 742, 738, 2414, 756,
	753, 1720, 2367, 2365, 2362, 2359, 1663, 693, 691, 684, 2373, 680, 2370, 702, 699, 696, 704, 1690, 1687, 2337,
	2336, 2334, 2332, 1624, 2329, 1622, 640, 637, 2344, 634, 2342, 630, 2340, 650, 648, 645, 2346, 655, 653, 1653,
	1651, 1649, 1655, 2612, 2597, 2595, 2571, 2568, 2565, 2576, 2534, 2529, 2526, 1787, 2540, 2537, 907, 904, 900,
	910, 2503, 2502, 2500, 2498, 1768, 2495, 1767, 2510, 2508, 2506, 869, 866, 863, 2513, 876, 874, 1782, 2720, 2713,
	2711, 2697, 2694, 2691, 2702, 2672, 2670, 2664, 1828, 2678, 2675, 2647, 2646, 2644, 2642, 1823, 2639, 1822, 2654,
	2652, 2650, 2657, 2771, 1855, 2765, 2762, 1850, 1849, 2751, 2749, 2747, 2754, 353, 2148, 344, 342, 336, 2142,
	332, 2140, 345, 1375, 1373, 306, 2130, 299, 2128, 295, 2125, 319, 314, 311, 2132, 1354, 1352, 1349, 1356, 262,
	257, 2101, 253, 2096, 2093, 274, 273, 267, 2107, 263, 2104, 280, 278, 275, 1316, 1311, 1308, 1320, 1318, 2052,
	202, 2050, 2044, 2040, 219, 2063, 212, 2060, 208, 2055, 224, 221, 2066, 1260, 1258, 1252, 231, 1248, 229, 1266,
	1264, 1261, 1268, 155, 1998, 153, 1996, 1994, 1991, 1988, 165, 164, 2007, 162, 2006, 159, 2003, 2000, 172, 171,
	169, 2012, 166, 2010, 1186, 1184, 1182, 1179, 175, 1176, 173, 1192, 1191, 1189, 1187, 176, 1194, 1193, 2313,
	2307, 2305, 592, 589, 2294, 2292, 2289, 578, 572, 568, 2297, 580, 1591, 2272, 2267, 2264, 1547, 538, 536, 529,
	2278, 525, 2275, 547, 544, 541, 1574, 1571, 2237, 2235, 2229, 1493, 2225, 1489, 478, 2247, 470, 2244, 465, 2241,
	493, 488, 484, 2250, 498, 495, 1536, 1533, 1530, 1539, 2187, 2186, 2184, 2182, 1432, 2179, 1430, 2176, 1427, 414,
	412, 2197, 409, 2195, 405, 2193, 2190, 426, 424, 421, 2203, 418, 2201, 431, 429, 1473, 1471, 1469, 1466, 434,
	1477, 1475, 2478, 2472, 2470, 2459, 2457, 2454, 2462, 803, 2437, 2432, 2429, 1726, 2443, 2440, 792, 789, 785,
	2401, 2399, 2393, 1702, 2389, 1699, 2411, 2408, 2405, 745, 741, 2415, 758, 755, 1721, 2358, 2357, 2355, 2353,
	1661, 2350, 1660, 2347, 1657, 2368, 2366, 2364, 2361, 1666, 690, 687, 2374, 683, 2372, 701, 698, 705, 1691, 1689,
	2619, 2617, 2610, 2608, 2605, 2613, 2593, 2588, 2585, 1803, 2599, 2596, 2563, 2561, 2555, 1797, 2551, 1795, 2573,
	2570, 2567, 2577, 2525, 2524, 2522, 2520, 1786, 2517, 1785, 2514, 1783, 2535, 2533, 2531, 2528, 1788, 2541, 2539,
	906, 903, 911, 2721, 1844, 2715, 2712, 1838, 1836, 2699, 2696, 2693, 2703, 1827, 1826, 1824, 2673, 2671, 2669,
	2666, 1829, 2679, 2677, 1858, 1857, 2772, 1854, 1853, 1851, 1856, 2766, 2764, 143, 1987, 139, 1986, 135, 133,
	131, 1984, 128, 1983, 125, 1981, 138, 137, 136, 1985, 1133, 1132, 1130, 112, 110, 1974, 107, 1973, 104, 1971,
	1969, 122, 121, 119, 117, 1977, 114, 1976, 124, 1115, 1114, 1112, 1110, 1117, 1116, 84, 83, 1953, 81, 1952, 78,
	1950, 1948, 1945, 94, 93, 91, 1959, 88, 1958, 85, 1955, 99, 97, 95, 1961, 1086, 1085, 1083, 1081, 1078, 100,
	1090, 1089, 1087, 1091, 49, 47, 1917, 44, 1915, 1913, 1910, 1907, 59, 1926, 56, 1925, 53, 1922, 1919, 66, 64,
	1931, 61, 1929, 1042, 1040, 1038, 71, 1035, 70, 1032, 68, 1048, 1047, 1045, 1043, 1050, 1049, 12, 10, 1869, 1867,
	1864, 1861, 21, 1880, 19, 1877, 1874, 1871, 28, 1888, 25, 1886, 22, 1883, 982, 980, 977, 974, 32, 30, 991, 989,
	987, 984, 34, 995, 994, 992, 2151, 2150, 2147, 2146, 2144, 356, 355, 354, 2149, 2139, 2138, 2136, 2134, 1359,
	343, 341, 338, 2143, 335, 2141, 348, 347, 346, 1376, 1374, 2124, 2123, 2121, 2119, 1326, 2116, 1324, 310, 308,
	305, 2131, 302, 2129, 298, 2127, 320, 318, 316, 313, 2133, 322, 321, 1355, 1353, 1351, 1357, 2092, 2091, 2089,
	2087, 1276, 2084, 1274, 2081, 1271, 259, 2102, 256, 2100, 252, 2098, 2095, 272, 269, 2108, 266, 2106, 281, 279,
	277, 1317, 1315, 1313, 1310, 282, 1321, 1319, 2039, 2037, 2035, 2032, 1203, 2029, 1200, 1197, 207, 2053, 205,
	2051, 201, 2049, 2046, 2043, 220, 218, 2064, 215, 2062, 211, 2059, 228, 226, 223, 2069, 1259, 1257, 1254, 232,
	1251, 230, 1267, 1265, 1263, 2316, 2315, 2312, 2311, 2309, 2314, 2304, 2303, 2301, 2299, 1593, 2308, 2306, 590,
	2288, 2287, 2285, 2283, 1578, 2280, 1577, 2295, 2293, 2291, 579, 577, 574, 571, 2298, 582, 581, 1592, 2263, 2262,
	2260, 2258, 1545, 2255, 1544, 2252, 1541, 2273, 2271, 2269, 2266, 1550, 535, 532, 2279, 528, 2277, 546, 543, 549,
	1575, 1573, 2224, 2222, 2220, 1486, 2217, 1485, 2214, 1482, 1479, 2238, 2236, 2234, 2231, 1496, 2228, 1492, 480,
	477, 2248, 473, 2246, 469, 2243, 490, 487, 2251, 497, 1537, 1535, 1532, 2477, 2476, 2474, 2479, 2469, 2468, 2466,
	2464, 1730, 2473, 2471, 2453, 2452, 2450, 2448, 1729, 2445, 1728, 2460, 2458, 2456, 2463, 805, 804, 2428, 2427,
	2425, 2423, 1725, 2420, 1724, 2417, 1722, 2438, 2436, 2434, 2431, 1727, 2444, 2442, 793, 791, 788, 795, 2388,
	2386, 2384, 1697, 2381, 1696, 2378, 1694, 1692, 2402, 2400, 2398, 2395, 1703, 2392, 1701, 2412, 2410, 2407, 751,
	748, 744, 2416, 759, 757, 1807, 2620, 2618, 1806, 1805, 2611, 2609, 2607, 2614, 1802, 1801, 1799, 2594, 2592,
	2590, 2587, 1804, 2600, 2598, 1794, 1793, 1791, 1789, 2564, 2562, 2560, 2557, 1798, 2554, 1796, 2574, 2572, 2569,
	2578, 1847, 1846, 2722, 1843, 1842, 1840, 1845, 2716, 2714, 1835, 1834, 1832, 1830, 1839, 1837, 2700, 2698, 2695,
	2704, 1817, 1811, 1810, 897, 862, 1777, 829, 826, 838, 1760, 1758, 808, 2481, 1741, 1740, 1738, 1743, 2624, 1818,
	2726, 2776, 782, 740, 737, 1715, 686, 679, 695, 1682, 1680, 639, 628, 2339, 647, 644, 1645, 1643, 1640, 1648,
	602, 600, 597, 595, 2320, 593, 2318, 609, 607, 604, 1611, 1610, 1608, 1606, 613, 1615, 1613, 2328, 926, 924, 892,
	886, 899, 857, 850, 2505, 1778, 824, 823, 821, 819, 2488, 818, 2486, 833, 831, 828, 840, 1761, 1759, 2649, 2632,
	2630, 2746, 2734, 2732, 2782, 2781, 570, 567, 1587, 531, 527, 523, 540, 1566, 1564, 476, 467, 463, 2240, 486,
	483, 1524, 1521, 1518, 1529, 411, 403, 2192, 399, 2189, 423, 416, 1462, 1457, 1454, 428, 1468, 1465, 2210, 366,
	363, 2158, 360, 2156, 357, 2153, 376, 373, 370, 2163, 1410, 1409, 1407, 1405, 382, 1402, 380, 1417, 1415, 1412,
	1421, 2175, 2174, 777, 774, 771, 784, 732, 725, 722, 2404, 743, 1716, 676, 674, 668, 2363, 665, 2360, 685, 1684,
	1681, 626, 624, 622, 2335, 620, 2333, 617, 2330, 641, 635, 649, 1646, 1644, 1642, 2566, 928, 925, 2530, 2527,
	894, 891, 888, 2501, 2499, 2496, 858, 856, 854, 851, 1779, 2692, 2668, 2665, 2645, 2643, 2640, 2651, 2768, 2759,
	2757, 2744, 2743, 2741, 2748, 352, 1382, 340, 337, 333, 1371, 1369, 307, 300, 296, 2126, 315, 312, 1347, 1342,
	1350, 261, 258, 250, 2097, 246, 2094, 271, 268, 264, 1306, 1301, 1298, 276, 1312, 1309, 2115, 203, 2048, 195,
	2045, 191, 2041, 213, 209, 2056, 1246, 1244, 1238, 225, 1234, 222, 1256, 1253, 1249, 1262, 2080, 2079, 154, 1997,
	150, 1995, 147, 1992, 1989, 163, 160, 2004, 156, 2001, 1175, 1174, 1172, 1170, 1167, 170, 1164, 167, 1185, 1183,
	1180, 1177, 174, 1190, 1188, 2025, 2024, 2022, 587, 586, 564, 559, 556, 2290, 573, 1588, 520, 518, 512, 2268,
	508, 2265, 530, 1568, 1565, 461, 457, 2233, 450, 2230, 446, 2226, 479, 471, 489, 1526, 1523, 1520, 397, 395,
	2185, 392, 2183, 389, 2180, 2177, 410, 2194, 402, 422, 1463, 1461, 1459, 1456, 1470, 2455, 799, 2433, 2430, 779,
	776, 773, 2397, 2394, 2390, 734, 728, 724, 746, 1717, 2356, 2354, 2351, 2348, 1658, 677, 675, 673, 670, 667, 688,
	1685, 1683, 2606, 2589, 2586, 2559, 2556, 2552, 927, 2523, 2521, 2518, 2515, 1784, 2532, 895, 893, 890, 2718,
	2709, 2707, 2689, 2687, 2684, 2663, 2662, 2660, 2658, 1825, 2667, 2769, 1852, 2760, 2758, 142, 141, 1139, 1138,
	134, 132, 129, 126, 1982, 1129, 1128, 1126, 1131, 113, 111, 108, 105, 1972, 101, 1970, 120, 118, 115, 1109, 1108,
	1106, 1104, 123, 1113, 1111, 82, 79, 1951, 75, 1949, 72, 1946, 92, 89, 86, 1956, 1077, 1076, 1074, 1072, 98,
	1069, 96, 1084, 1082, 1079, 1088, 1968, 1967, 48, 45, 1916, 42, 1914, 39, 1911, 1908, 60, 57, 54, 1923, 50, 1920,
	1031, 1030, 1028, 1026, 67, 1023, 65, 1020, 62, 1041, 1039, 1036, 1033, 69, 1046, 1044, 1944, 1943, 1941, 11, 9,
	1868, 7, 1865, 1862, 1859, 20, 1878, 16, 1875, 13, 1872, 970, 968, 966, 963, 29, 960, 26, 23, 983, 981, 978, 975,
	33, 971, 31, 990, 988, 985, 1906, 1904, 1902, 993, 351, 2145, 1383, 331, 330, 328, 326, 2137, 323, 2135, 339,
	1372, 1370, 294, 293, 291, 289, 2122, 286, 2120, 283, 2117, 309, 303, 317, 1348, 1346, 1344, 245, 244, 242, 2090,
	239, 2088, 236, 2085, 2082, 260, 2099, 249, 270, 1307, 1305, 1303, 1300, 1314, 189, 2038, 186, 2036, 183, 2033,
	2030, 2026, 206, 198, 2047, 194, 216, 1247, 1245, 1243, 1240, 227, 1237, 1255, 2310, 2302, 2300, 2286, 2284,
	2281, 565, 563, 561, 558, 575, 1589, 2261, 2259, 2256, 2253, 1542, 521, 519, 517, 514, 2270, 511, 533, 1569,
	1567, 2223, 2221, 2218, 2215, 1483, 2211, 1480, 459, 456, 453, 2232, 449, 474, 491, 1527, 1525, 1522, 2475, 2467,
	2465, 2451, 2449, 2446, 801, 800, 2426, 2424, 2421, 2418, 1723, 2435, 780, 778, 775, 2387, 2385, 2382, 2379,
	1695, 2375, 1693, 2396, 735, 733, 730, 727, 749, 1718, 2616, 2615, 2604, 2603, 2601, 2584, 2583, 2581, 2579,
	1800, 2591, 2550, 2549, 2547, 2545, 1792, 2542, 1790, 2558, 929, 2719, 1841, 2710, 2708, 1833, 1831, 2690, 2688,
	2686, 1815, 1809, 1808, 1774, 1756, 1754, 1737, 1736, 1734, 1739, 1816, 1711, 1676, 1674, 633, 629, 1638, 1636,
	1633, 1641, 598, 1605, 1604, 1602, 1600, 605, 1609, 1607, 2327, 887, 853, 1775, 822, 820, 1757, 1755, 1584, 524,
	1560, 1558, 468, 464, 1514, 1511, 1508, 1519, 408, 404, 400, 1452, 1447, 1444, 417, 1458, 1455, 2208, 364, 361,
	358, 2154, 1401, 1400, 1398, 1396, 374, 1393, 371, 1408, 1406, 1403, 1413, 2173, 2172, 772, 726, 723, 1712, 672,
	669, 666, 682, 1678, 1675, 625, 623, 621, 618, 2331, 636, 632, 1639, 1637, 1635, 920, 918, 884, 880, 889, 849,
	848, 847, 846, 2497, 855, 852, 1776, 2641, 2742, 2787, 1380, 334, 1367, 1365, 301, 297, 1340, 1338, 1335, 1343,
	255, 251, 247, 1296, 1291, 1288, 265, 1302, 1299, 2113, 204, 196, 192, 2042, 1232, 1230, 1224, 214, 1220, 210,
	1242, 1239, 1235, 1250, 2077, 2075, 151, 148, 1993, 144, 1990, 1163, 1162, 1160, 1158, 1155, 161, 1152, 157,
	1173, 1171, 1168, 1165, 168, 1181, 1178, 2021, 2020, 2018, 2023, 585, 560, 557, 1585, 516, 509, 1562, 1559, 458,
	447, 2227, 472, 1516, 1513, 1510, 398, 396, 393, 390, 2181, 386, 2178, 407, 1453, 1451, 1449, 1446, 420, 1460,
	2209, 769, 764, 720, 712, 2391, 729, 1713, 664, 663, 661, 659, 2352, 656, 2349, 671, 1679, 1677, 2553, 922, 919,
	2519, 2516, 885, 883, 881, 2685, 2661, 2659, 2767, 2756, 2755, 140, 1137, 1136, 130, 127, 1125, 1124, 1122, 1127,
	109, 106, 102, 1103, 1102, 1100, 1098, 116, 1107, 1105, 1980, 80, 76, 73, 1947, 1068, 1067, 1065, 1063, 90, 1060,
	87, 1075, 1073, 1070, 1080, 1966, 1965, 46, 43, 40, 1912, 36, 1909, 1019, 1018, 1016, 1014, 58, 1011, 55, 1008,
	51, 1029, 1027, 1024, 1021, 63, 1037, 1034, 1940, 1939, 1937, 1942, 8, 1866, 4, 1863, 1, 1860, 956, 954, 952,
	949, 946, 17, 14, 969, 967, 964, 961, 27, 957, 24, 979, 976, 972, 1901, 1900, 1898, 1896, 986, 1905, 1903, 350,
	349, 1381, 329, 327, 324, 1368, 1366, 292, 290, 287, 284, 2118, 304, 1341, 1339, 1337, 1345, 243, 240, 237, 2086,
	233, 2083, 254, 1297, 1295, 1293, 1290, 1304, 2114, 190, 187, 184, 2034, 180, 2031, 177, 2027, 199, 1233, 1231,
	1229, 1226, 217, 1223, 1241, 2078, 2076, 584, 555, 554, 552, 550, 2282, 562, 1586, 507, 506, 504, 502, 2257, 499,
	2254, 515, 1563, 1561, 445, 443, 441, 2219, 438, 2216, 435, 2212, 460, 454, 475, 1517, 1515, 1512, 2447, 798,
	797, 2422, 2419, 770, 768, 766, 2383, 2380, 2376, 721, 719, 717, 714, 731, 1714, 2602, 2582, 2580, 2548, 2546,
	2543, 923, 921, 2717, 2706, 2705, 2683, 2682, 2680, 1771, 1752, 1750, 1733, 1732, 1731, 1735, 1814, 1707, 1670,
	1668, 1631, 1629, 1626, 1634, 1599, 1598, 1596, 1594, 1603, 1601, 2326, 1772, 1753, 1751, 1581, 1554, 1552, 1504,
	1501, 1498, 1509, 1442, 1437, 1434, 401, 1448, 1445, 2206, 1392, 1391, 1389, 1387, 1384, 359, 1399, 1397, 1394,
	1404, 2171, 2170, 1708, 1672, 1669, 619, 1632, 1630, 1628, 1773, 1378, 1363, 1361, 1333, 1328, 1336, 1286, 1281,
	1278, 248, 1292, 1289, 2111, 1218, 1216, 1210, 197, 1206, 193, 1228, 1225, 1221, 1236, 2073, 2071, 1151, 1150,
	1148, 1146, 152, 1143, 149, 1140, 145, 1161, 1159, 1156, 1153, 158, 1169, 1166, 2017, 2016, 2014, 2019, 1582,
	510, 1556, 1553, 452, 448, 1506, 1500, 394, 391, 387, 1443, 1441, 1439, 1436, 1450, 2207, 765, 716, 713, 1709,
	662, 660, 657, 1673, 1671, 916, 914, 879, 878, 877, 882, 1135, 1134, 1121, 1120, 1118, 1123, 1097, 1096, 1094,
	1092, 103, 1101, 1099, 1979, 1059, 1058, 1056, 1054, 77, 1051, 74, 1066, 1064, 1061, 1071, 1964, 1963, 1007,
	1006, 1004, 1002, 999, 41, 996, 37, 1017, 1015, 1012, 1009, 52, 1025, 1022, 1936, 1935, 1933, 1938, 942, 940,
	938, 935, 932, 5, 2, 955, 953, 950, 947, 18, 943, 15, 965, 962, 958, 1895, 1894, 1892, 1890, 973, 1899, 1897,
	1379, 325, 1364, 1362, 288, 285, 1334, 1332, 1330, 241, 238, 234, 1287, 1285, 1283, 1280, 1294, 2112, 188, 185,
	181, 178, 2028, 1219, 1217, 1215, 1212, 200, 1209, 1227, 2074, 2072, 583, 553, 551, 1583, 505, 503, 500, 513,
	1557, 1555, 444, 442, 439, 436, 2213, 455, 451, 1507, 1505, 1502, 796, 763, 762, 760, 767, 711, 710, 708, 706,
	2377, 718, 715, 1710, 2544, 917, 915, 2681, 1627, 1597, 1595, 2325, 1769, 1749, 1747, 1499, 1438, 1435, 2204,
	1390, 1388, 1385, 1395, 2169, 2167, 1704, 1665, 1662, 1625, 1623, 1620, 1770, 1329, 1282, 1279, 2109, 1214, 1207,
	1222, 2068, 2065, 1149, 1147, 1144, 1141, 146, 1157, 1154, 2013, 2011, 2008, 2015, 1579, 1549, 1546, 1495, 1487,
	1433, 1431, 1428, 1425, 388, 1440, 2205, 1705, 658, 1667, 1664, 1119, 1095, 1093, 1978, 1057, 1055, 1052, 1062,
	1962, 1960, 1005, 1003, 1000, 997, 38, 1013, 1010, 1932, 1930, 1927, 1934, 941, 939, 936, 933, 6, 930, 3, 951,
	948, 944, 1889, 1887, 1884, 1881, 959, 1893, 1891, 35, 1377, 1360, 1358, 1327, 1325, 1322, 1331, 1277, 1275,
	1272, 1269, 235, 1284, 2110, 1205, 1204, 1201, 1198, 182, 1195, 179, 1213, 2070, 2067, 1580, 501, 1551, 1548,
	440, 437, 1497, 1494, 1490, 1503, 761, 709, 707, 1706, 913, 912, 2198, 1386, 2164, 2161, 1621, 1766, 2103, 1208,
	2058, 2054, 1145, 1142, 2005, 2002, 1999, 2009, 1488, 1429, 1426, 2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954,
	1001, 998, 1924, 1921, 1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882, 1323, 1273, 1270,
	2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576, 1543, 1540, 1484, 1481, 1478, 1491, 1700
};

using ModuleBitCountType = std::array<int, CodewordDecoder::BARS_IN_MODULE>;

static ModuleBitCountType SampleBitCounts(const ModuleBitCountType& moduleBitCount)
{
	float bitCountSum = static_cast<float>(Reduce(moduleBitCount));
	ModuleBitCountType result;
	result.fill(0);
	int bitCountIndex = 0;
	int sumPreviousBits = 0;
	for (int i = 0; i < CodewordDecoder::MODULES_IN_CODEWORD; i++) {
		float sampleIndex = bitCountSum / (2 * CodewordDecoder::MODULES_IN_CODEWORD) + (i * bitCountSum) / CodewordDecoder::MODULES_IN_CODEWORD;
		if (sumPreviousBits + moduleBitCount[bitCountIndex] <= sampleIndex) {
			sumPreviousBits += moduleBitCount[bitCountIndex];
			bitCountIndex++;
			if (bitCountIndex == Size(moduleBitCount)) { // this check is not done in original code, so I guess this should not happen?
				break;
			}
		}
		result[bitCountIndex]++;
	}
	return result;
}

static int GetBitValue(const ModuleBitCountType& moduleBitCount)
{
	int result = 0;
	for (size_t i = 0; i < moduleBitCount.size(); i++)
		for (int bit = 0; bit < moduleBitCount[i]; bit++)
			AppendBit(result, i % 2 == 0);
	return result;
}

static int GetDecodedCodewordValue(const ModuleBitCountType& moduleBitCount)
{
	int decodedValue = GetBitValue(moduleBitCount);
	return CodewordDecoder::GetCodeword(decodedValue) == -1 ? -1 : decodedValue;
}

static constexpr int getSymbol(int idx)
{
	return SYMBOL_TABLE[idx] | 0x10000;
}

static int GetClosestDecodedValue(const ModuleBitCountType& moduleBitCount)
{
#if 1 // put 87kB on heap and calucate per process on first use -> 7% smaller binary
	static const auto ratioTable = []() {
		auto table = std::vector<std::array<float, CodewordDecoder::BARS_IN_MODULE>>(SYMBOL_COUNT);
#else // put 87kB in .rodata shared by all processes and calcuate during compilation
	static constexpr const auto ratioTable = []() constexpr {
		auto table = std::array<std::array<float, CodewordDecoder::BARS_IN_MODULE>, SYMBOL_COUNT>();
#endif
		for (int i = 0; i < SYMBOL_COUNT; i++) {
			int currentSymbol = getSymbol(i);
			int currentBit = currentSymbol & 0x1;
			for (int j = 0; j < CodewordDecoder::BARS_IN_MODULE; j++) {
				int8_t size = 0;
				while ((currentSymbol & 0x1) == currentBit) {
					size += 1;
					currentSymbol >>= 1;
				}
				currentBit = currentSymbol & 0x1;
				table[i][CodewordDecoder::BARS_IN_MODULE - j - 1] = size / 17.f; // MODULES_IN_CODEWORD
			}
		}
		return table;
	}();

	int bitCountSum = Reduce(moduleBitCount);
	std::array<float, CodewordDecoder::BARS_IN_MODULE> bitCountRatios = {};
	if (bitCountSum > 1) {
		for (int i = 0; i < CodewordDecoder::BARS_IN_MODULE; i++) {
			bitCountRatios[i] = moduleBitCount[i] / (float)bitCountSum;
		}
	}
	float bestMatchError = std::numeric_limits<float>::max();
	int bestMatch = -1;
	for (size_t j = 0; j < ratioTable.size(); j++) {
		float error = 0.0f;
		auto& ratioTableRow = ratioTable[j];
		for (int k = 0; k < CodewordDecoder::BARS_IN_MODULE; k++) {
			float diff = ratioTableRow[k] - bitCountRatios[k];
			error += diff * diff;
			if (error >= bestMatchError) {
				break;
			}
		}
		if (error < bestMatchError) {
			bestMatchError = error;
			bestMatch = getSymbol(j);
		}
	}
	return bestMatch;
}

int
CodewordDecoder::GetDecodedValue(const std::array<int, BARS_IN_MODULE>& moduleBitCount)
{
	int decodedValue = GetDecodedCodewordValue(SampleBitCounts(moduleBitCount));
	if (decodedValue != -1) {
		return decodedValue;
	}
	return GetClosestDecodedValue(moduleBitCount);
}

/**
* @param symbol encoded symbol to translate to a codeword
* @return the codeword corresponding to the symbol.
*/
int
CodewordDecoder::GetCodeword(int symbol)
{
	if ((symbol & 0xFFFF0000) != 0x10000)
		return -1;
	symbol &= 0xFFFF;
	auto it = std::lower_bound(SYMBOL_TABLE.begin(), SYMBOL_TABLE.end(), symbol);
	if (it != SYMBOL_TABLE.end() && *it == symbol) {
		return (CODEWORD_TABLE[it - SYMBOL_TABLE.begin()] - 1) % NUMBER_OF_CODEWORDS;
	}
	return -1;
}

} // Pdf417
} // ZXing
